package model

import (
	"errors"
	"fmt"
	"strings"
	"time"

	"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"
)

func InsertPubTask(task PubTask) (PubTask, error) {
	o := orm.NewOrm()
	task.CreateTime = time.Now()
	_, err := o.Insert(&task)
	return task, err
}

func RePublish(id int) error{
	o := orm.NewOrm()
	task := PubTask{Id:id,Status:0,Msg:""}
	_, err := o.Update(&task,"status","msg")
	return err
}

func UpdatePubtask(task PubTask) (PubTask, error) {
	o := orm.NewOrm()

	prestatus := []int{}
	switch task.Status {
	case Pub_Status_Success, Pub_Status_Fail:
		prestatus = append(prestatus, Pub_Status_Pub_Start)
	case Pub_Status_Pub_Start:
		prestatus = append(prestatus, Pub_Status_Pubing)
	case Pub_Status_Pubing:
		prestatus = append(prestatus, Pub_Status_Nopub)
	case Pub_Status_Nopub:
		prestatus = append(prestatus, Pub_Status_Pubing, Pub_Status_Pub_Start)
	}

	statustime := time.Now().Format("2006-01-02 15:04:05")
	cols := []string{"status", "msg", "status_time", "error_count"}
	args := []interface{}{task.Status, task.Msg, statustime, task.ErrorCount}
	if !task.EndTime.IsZero() {
		cols = append(cols, "end_time")
		args = append(args, task.EndTime.Format("2006-01-02 15:04:05"))
	}

	sep := "` = ?, `"
	setNames := strings.Join(cols, sep)
	// 校验状态是前置状态
	sql := fmt.Sprintf("UPDATE pub_task SET `%s` = ? WHERE id = ?", setNames)
	args = append(args, task.Id)

	if len(prestatus) > 0 {
		sql += " AND ( "
		val := []string{}
		for _, v := range prestatus {
			val = append(val, "status = ?")
			args = append(args, v)
		}
		sql += strings.Join(val, " OR ")
		sql += " )"
	}
	beego.Info(sql, args, len(args))

	res, err := o.Raw(sql, args).Exec()
	if err != nil {
		return task, err
	}

	num, err := res.RowsAffected()
	if err != nil {
		return task, err
	}

	if num == 0 {
		return task, errors.New(fmt.Sprintf("prestatus is not %d", prestatus))
	}

	return task, err
}

func PubTaskById(id int) (PubTask, error) {
	o := orm.NewOrm()
	task := PubTask{Id: id}
	err := o.Read(&task)
	return task, err
}

func GetNeedPubTask() (PubTask, error) {
	pub := PubTask{}
	o := orm.NewOrm()
	err := o.Begin()
	if err != nil {
		o.Rollback()
		return pub, err
	}

	err = o.Raw("select * from pub_task where status = ? limit 1 for update", Pub_Status_Nopub).QueryRow(&pub)
	if err != nil {
		o.Rollback()
		return pub, err
	}

	pub.Status = Pub_Status_Pubing
	pub.StatusTime = time.Now()
	_, err = o.Update(&pub, "status", "status_time")
	if err != nil {
		o.Rollback()
		return pub, err
	}

	err = o.Commit()
	if err != nil {
		o.Rollback()
		return pub, err
	}

	return pub, nil
}

func NoConnectTask() ([]PubTask, error) {
	o := orm.NewOrm()
	pubs := []PubTask{}
	_, err := o.Raw("select * from pub_task where status = ? OR status = ?", Pub_Status_Pubing, Pub_Status_Pub_Start).QueryRows(&pubs)
	if err != nil {
		return nil, err
	}
	return pubs, nil
}


func ListPubTask()  ([]PubTask,error){
	o := orm.NewOrm()
	pubTasks :=  []PubTask{}
	s := "select * from pub_task"
	_,err := o.Raw(s).QueryRows(&pubTasks)
	return pubTasks,err
}

func ListPubTaskByPage(page int,size int)  (pubTasks []PubTask,count int,err error){
	o := orm.NewOrm()
	s := "select * from pub_task order by id desc limit ?,?"
	_,err = o.Raw(s, (page-1)*size, size).QueryRows(&pubTasks)
	if err != nil{
		return nil,0,err
	}
	sql := `select count(*) from pub_task`
	err = o.Raw(sql).QueryRow(&count)
	if err != nil{
		return nil,0,err
	}
	return pubTasks,count,err
}
